<!DOCTYPE html>












  


<html class="theme-next gemini use-motion" lang="Chinese">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2"/>
<meta name="theme-color" content="#222">












<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />






















<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=6.4.0" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=6.4.0">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=6.4.0">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=6.4.0">


  <link rel="mask-icon" href="/images/logo.svg?v=6.4.0" color="#222">









<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '6.4.0',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: false,
    fastclick: false,
    lazyload: false,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>


  




  <meta property="og:type" content="website">
<meta property="og:title" content="政子的博客">
<meta property="og:url" content="http://blog.zhengzi.me/page/2/index.html">
<meta property="og:site_name" content="政子的博客">
<meta property="og:locale" content="Chinese">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="政子的博客">






  <link rel="canonical" href="http://blog.zhengzi.me/page/2/"/>



<script type="text/javascript" id="page.configurations">
  CONFIG.page = {
    sidebar: "",
  };
</script>

  <title>政子的博客</title>
  









  <noscript>
  <style type="text/css">
    .use-motion .motion-element,
    .use-motion .brand,
    .use-motion .menu-item,
    .sidebar-inner,
    .use-motion .post-block,
    .use-motion .pagination,
    .use-motion .comments,
    .use-motion .post-header,
    .use-motion .post-body,
    .use-motion .collection-title { opacity: initial; }

    .use-motion .logo,
    .use-motion .site-title,
    .use-motion .site-subtitle {
      opacity: initial;
      top: initial;
    }

    .use-motion {
      .logo-line-before i { left: initial; }
      .logo-line-after i { right: initial; }
    }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="Chinese">

  
  
    
  

  <div class="container sidebar-position-left 
  page-home">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">政子的博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
    
      
        <p class="site-subtitle">强迫症|学习者|伪文青</p>
      
    
  </div>

  <div class="site-nav-toggle">
    <button aria-label="Toggle navigation bar">
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>



<nav class="site-nav">
  
    <ul id="menu" class="menu">
      
        
        
        
          
          <li class="menu-item menu-item-home">
    <a href="/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-home"></i> <br />Home</a>
  </li>
        
        
        
          
          <li class="menu-item menu-item-about">
    <a href="/about/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-user"></i> <br />About</a>
  </li>
        
        
        
          
          <li class="menu-item menu-item-tags">
    <a href="/tags/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />Tags</a>
  </li>
        
        
        
          
          <li class="menu-item menu-item-archives">
    <a href="/archives/" rel="section">
      <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />Archives</a>
  </li>

      
      
    </ul>
  

  

  
</nav>



  



</div>
    </header>

    


    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          
            

          
          <div id="content" class="content">
            
  <section id="posts" class="posts-expand">
    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://blog.zhengzi.me/2017/09/05/leetcode-palindrome-number/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Jason Bian">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="政子的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/09/05/leetcode-palindrome-number/" itemprop="url">
                  LeetCode-Palindrome Number
                </a>
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              

              
                
              

              <time title="Created: 2017-09-05 00:59:10" itemprop="dateCreated datePublished" datetime="2017-09-05T00:59:10+08:00">2017-09-05</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Modified: 2018-08-21 17:49:42" itemprop="dateModified" datetime="2018-08-21T17:49:42+08:00">2018-08-21</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/算法/" itemprop="url" rel="index"><span itemprop="name">算法</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p><a href="https://leetcode.com/problems/palindrome-number/description/" target="_blank" rel="noopener">https://leetcode.com/problems/palindrome-number/description/</a> 又水了一道很简单的题，求回文数，只要记着负数肯定不是回文数就可以了。 简单从左右分别开始比较：</p>
<p>class Solution(object):<br>    def isPalindrome(self, x):<br>        “””<br>        :type x: int<br>        :rtype: bool<br>        “””<br>        if x&gt;=0:<br>            xStr=str(x)<br>            left=0<br>            right=len(xStr)-1<br>            while right-left&gt;=1:<br>                if xStr[left] != xStr[right]:<br>                    return False<br>                left=left+1<br>                right=right-1<br>            return True<br>        else:<br>            return False</p>
<p>用时192ms 用Python字符串反转的方式最简洁，一行搞定：</p>
<p>class Solution(object):<br>    def isPalindrome(self, x):<br>        “””<br>        :type x: int<br>        :rtype: bool<br>        “””<br>        return str(x) == str(x)[::-1]</p>
<p>用时205ms，和上一种方法几乎一样</p>

          
        
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://blog.zhengzi.me/2017/09/04/leetcode-reverse-integer/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Jason Bian">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="政子的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/09/04/leetcode-reverse-integer/" itemprop="url">
                  LeetCode-Reverse Integer
                </a>
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              

              
                
              

              <time title="Created: 2017-09-04 00:57:29" itemprop="dateCreated datePublished" datetime="2017-09-04T00:57:29+08:00">2017-09-04</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Modified: 2018-08-21 17:49:42" itemprop="dateModified" datetime="2018-08-21T17:49:42+08:00">2018-08-21</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/算法/" itemprop="url" rel="index"><span itemprop="name">算法</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p><a href="https://leetcode.com/problems/reverse-integer/" target="_blank" rel="noopener">https://leetcode.com/problems/reverse-integer/</a> LeetCode最简单的题目之一，不过要好好审题。 比如题目要求—— The input is assumed to be a 32-bit signed integer. Your function should <strong>return 0 when the reversed integer overflows</strong>. 我根本没有看见粗体的renversed，所以一直对输入是不是符合32位整数进行判断，结果闹了很久才明白为啥最后几个case没法a。 复习：32位有符号整数范围 -2^31~2^31-1，剩下使用Python应该没有任何问题。 下面的思路是将数字转换成字符串然后反转：</p>
<p>class Solution(object):<br>    def reverse(self, x):<br>        “””<br>        :type x: int<br>        :rtype: int<br>        “””<br>        sign=1<br>        if x&lt;0:<br>            sign=-1<br>            x=-x<br>        xRev=int(str(x)[::-1])<br>        if xRev&lt;2*<em>31:<br>            return sign</em>xRev<br>        else:<br>            return 0</p>
<p>用时52ms 换种思路，使用最简单的整除和取余：</p>
<p>class Solution(object):<br>    def reverse(self, x):<br>        “””<br>        :type x: int<br>        :rtype: int<br>        “””<br>        sign=1<br>        if x&lt;0:<br>            sign=-1<br>            x=-x<br>        elif x==0:<br>            sign=0<br>        xRev=’’<br>        while(x&gt;0):<br>            xRev=xRev+str(x%10)<br>            x=int(x/10)</p>
<pre><code>if sign==0 or int(xRev)&gt;=2**31:
    return 0
else:
    return sign*int(xRev)
</code></pre><p>因为加了循环，所以用时稍长一些，65ms</p>

          
        
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://blog.zhengzi.me/2017/08/31/e5-85-b0-e5-b7-9e-e5-b0-8f-e8-ae-b0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Jason Bian">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="政子的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/08/31/e5-85-b0-e5-b7-9e-e5-b0-8f-e8-ae-b0/" itemprop="url">
                  兰州小记
                </a>
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              

              
                
              

              <time title="Created: 2017-08-31 23:26:06" itemprop="dateCreated datePublished" datetime="2017-08-31T23:26:06+08:00">2017-08-31</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Modified: 2018-08-21 17:49:42" itemprop="dateModified" datetime="2018-08-21T17:49:42+08:00">2018-08-21</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/随笔/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>时日已至伏末，先别问秋老虎可不可怕，仅是鼻炎已经足以让我怀疑有一个连的人在想我。 话归正题，兰州在我心中的形象由两部分，一半像兰州烟上（我最喜欢吉祥兰州硬盒上的那个红色镶金的图案）那样：悠悠兰州，九天揽秀，另一半是爽朗直接，像兰州公交车司机一样，可以跳下车跟出租车对骂。总体来讲，用人来形容就是一个很飘渺但又古朴纯净的三四十岁胡子邋遢瘦削的硬汉。总之，矛盾满满。不过这一点不想展开去说，说说最近在兰州的见闻吧。 按照惯例，每次回家都要去张掖路逛逛，每次去逛也都盼着能有点什么不一样，但又担心不一样的地方多了我会忘记之前是什么样子。不过到目前为止，我的担心都是多余的。对我来讲，上半年改变最大的大概就是共享单车了。张掖路也是如此，但不是漫山遍野的自行车。为了不让单车进入，步行街的路障间隙更小了——将将够钻进去一条腿——进去以后擦一把汗，开始感慨前些日子的减肥真他丫有效，不然老夫就要卡死在这里了。 为什么念念不忘的是张掖路？除了之前总在这里买些衣服鞋子，让我逐渐摸清哪家店的沙发睡觉舒服以外，就是人多。我喜欢这里，总能让我沾沾人气儿，但又不必拘束自己。我喜欢看这里的人。 有吹着口哨吊儿郎当的“小社会”，有大包小包打招呼都腾不出手的时尚girl，有大胆往前走绝不向两边看的外卖小哥，也有讲着今儿鸡蛋多少钱亚欧超市是不是减价的大妈大爷，更多的是手扣着手面色红润的小情侣们。手里拎本儿Kindle，眼睛像磕睡狗一样眯起来望着这条街的，可能就只我一个了。 看着，我突然发现一个大问题——每个人，他们，居然，都，在讲话！成群结队成双成对的人在互相讲话，独自一个的人要么在讲电话，要么不知嘴里在嘟囔着什么。“怎么会这样”我自言自语。 为什么人人都会说话，为什么人人都在说话，人人都在说什么话？想回答这几个问题，着实有些难度，也很难在一篇小记中去讲。但培根问我的一个问题很有意思：“很多科学实验证明，猩猩也有语言，那么它跟人有什么不一样呢？它们有意识么？”这个问题就更有意思了。我认为解答这个问题的关键大概在于大猩猩有没有形成判断动词——是，也就是英文中的be动词。如果没有，那么它们还不能领会“存在”，只能通过语言表达诸存在者。在这个角度看，它们没有存在意义上的意识。再来看人类，就很有意思了。他们不仅仅可以领会经验上的存在物，更能领会超验的东西。比如——金钱、国家、社会、甚至是爱情。这些存在者的存在，没有意识，是无法领会的。 话又说回到爱情。之前看过一个理论，如果情侣之前无话可说，就很难有幸福感可言。说明充分的交流沟通是人与人之间构成伴侣的一个非常重要的条件。回过神看见商圈门前的一对对们，虽然高矮胖瘦形态各异，甚至肤色都有所不同。但都可以相爱——他们的十指都紧扣在一起，开心地讲着什么事情。 说的也巧，最近从臻那边听到了两个真实的故事。 一个是臻的父母 他老爸最开始不会做饭，直到他妈妈怀了他，他爸就磕磕绊绊在他妈妈的指导下学习做饭，每次他妈妈晚上饿了，他爸都二话不说去做夜宵，再后来，就是他爸一直做饭了。 他爸妈也不怎么吵架，就算吵得最厉害，也不超过半个小时，他爸就问他妈要不要泡个茶歇一会儿，他妈妈也欣然同意。他有一次问起他爸妈，“问题还没解决为啥就不吵了？”他妈妈说：“其实吵架的时候就已经想好要让一些步了，反正这么多年都是这样。”他爸爸说：“和你妈一吵架，我就心疼了，她肯定也知道我的想法了，所以我还是老老实实服软吧。” 另一个是臻在旅途中还遇到的一对金婚夫妇，在他们家中借宿了一天，听到了许多他们过往的故事。 夫妻俩都很大年纪了，奶奶叫那个阿公“酷哥”，阿公叫那个奶奶“宝贝”。那天阿公晚上要出去一趟，两个人还要拥抱之后，吻一下额头，才肯分开。奶奶趁着爷爷出去，偷偷告诉臻，她这一辈子最开心的事情，就是把当年那个连一句想你都不会说的闷葫芦，变成了现在只要离开一会儿，就关切的不行，还要用爱你结尾的老小孩~ 听完这些故事，当时的心情已是惘然。 现在回想，能拥有这样的爱情的人，该是有多可爱呀。一辈子不长，撞上好运气，能享受大富大贵的可能都比遇到这样一个人并且相处的如此之美的机会大太多。所以，要珍惜身边的人儿，你相信她，她相信你，两人都相信这样的生活，以后才可能就是如此了。臻，你讲，是不是这样？ 自张掖路一游之后，我对黄河风情线念念不忘。所以决定沿黄河南岸分别来一次骑行和跑步。 一路上最有意思的事情莫过于穿行在沿途的广场舞们中间，伴着异域风情高难度的新疆舞（是的，兰州今年流行这个），她们根本不为所动，就像冲进了一个正在被扭曲中的魔方，此情此景用一个字来形容，就是群魔乱舞。 另外，跑步的时候我还答应了一件事：未来要和“吃货”（此处简写）一起去东营逛逛，看看共和国最年轻的那片土地。或许，那边会的是一个比我曾经想去的巴颜喀拉山更神奇的地方呢。不，两个地方都要去，一起去看看究竟哪里更是希望。此处at她。 在黄河北岸骑车，穿过兰州音乐厅和城市规划馆的时候，我忍不住驻足，去欣赏她们。很有意思，一个被霓虹灯过度装点而另一个是被黑夜过度吞噬。终于，兰州也不再是那片朦朦胧胧的工业灰，她变得清晰年轻性感起来。 最后，贴几张雨后兰州的照片作结束吧。 <a href="http://blog.zhengzi.me/wp-content/uploads/2017/08/微信图片_20170831232345.jpg"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/08/微信图片_20170831232345.jpg" alt=""></a> <a href="http://blog.zhengzi.me/wp-content/uploads/2017/08/微信图片_20170831232355.jpg"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/08/微信图片_20170831232355.jpg" alt=""></a> <a href="http://blog.zhengzi.me/wp-content/uploads/2017/08/微信图片_20170831232401.jpg"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/08/微信图片_20170831232401.jpg" alt=""></a></p>

          
        
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://blog.zhengzi.me/2017/05/15/e5-86-99-e5-9c-a8-e4-ba-8c-e5-88-b7-e3-80-8a-e6-91-94-e8-b7-a4-e5-90-a7-ef-bc-8c-e7-88-b8-e7-88-b8-ef-bc-81-e3-80-8b-e4-b9-8b-e5-90-8e/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Jason Bian">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="政子的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/05/15/e5-86-99-e5-9c-a8-e4-ba-8c-e5-88-b7-e3-80-8a-e6-91-94-e8-b7-a4-e5-90-a7-ef-bc-8c-e7-88-b8-e7-88-b8-ef-bc-81-e3-80-8b-e4-b9-8b-e5-90-8e/" itemprop="url">
                  写在二刷《摔跤吧，爸爸！》之后
                </a>
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              

              
                
              

              <time title="Created: 2017-05-15 01:32:34" itemprop="dateCreated datePublished" datetime="2017-05-15T01:32:34+08:00">2017-05-15</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Modified: 2018-08-21 17:49:42" itemprop="dateModified" datetime="2018-08-21T17:49:42+08:00">2018-08-21</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/随笔/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>好电影是值得多看几遍的。 说实话，这几个月我都没有进电影院，更没有看过最近有争论所谓的这些国产烂片或者说是美国大片。对这部电影，虽然没有对比，但不能阻碍我认为它是一部好片。 虽然两次看的是同一部电影，但我每次的关注点一定是完全不同的。第一遍是随着影片的进程，不去思考过多，而是把自己融入电影之中，心情和大脑都去主动跟随剧情的发展，完全按照导演和编剧的思路欣赏。如果这是一部好片，那么心情一定会起起伏伏，倘若恰巧情节还比较紧凑，那么一场电影看下来必定是淋漓大汗。第二遍呢，我会选择从片中走出来，在看的时候去思考人物的性格、导演对情节的安排以及场内观众们的表现，看完后必定会有许多新的发现，有时候或许还能看出哪里是被引入的时候经过剪裁的，人物应该在哪里可以更活。 首刷的时候，我大概和其他观众一样，随着两个小姑娘的视角，内心跟随她们一起成长，一起对父亲肃然起敬，甚至国歌响的那一刹那，我也跟随她们一起感动。 二刷的时候，我注意到了几个有趣的细节。 第一个是父亲不顾村里人的笑话，不顾官员的嘲讽，更不顾录像厅老板的眼神，每一次出场的眼神都温和却坚定；但却因自己特殊照顾女儿却导致女儿差点被体育学校开出流泪，这是多坚强的泪水！ 第二个是父亲不论是在女儿消极怠练还是她们跑去参加别人的婚礼惹他生气甚至是女儿在教练那边学到了新的技巧而趾高气昂地嫌弃他的办法老旧的时候，他都没有打过一次女儿（每次都是她们的哥哥背锅）。父亲虽然严厉，但绝不毒辣，他对女儿的爱不亚于天下任何的父亲。 第三个是我认为是一个片段可能被删减，大概是父亲应该花几句话的时间去解释一下他为了让女儿摔跤不只是为了自己的梦想，还是为了女儿摆脱印度社会对于女性的不平等，让他的女儿过得更好一些。虽然在婚礼后新娘和女孩们的对话中可以看出一些，但依旧感觉不够浓厚，毕竟从父亲口中讲出来可以让电影主题更加深化，情节也更合人物性格一些（更可以让许多认为父亲是在强加自己的意志在女儿身上的人闭嘴）。而这一点我认为在中国人的心里认同性还是挺高。感谢牛三岁提供的生动素材，比如父母让孩子学习钢琴之类的乐器，这些乐器很可能是父母年轻时候未竟的梦想，现在让孩子去学，目的不仅仅是为了让子女去为他们比赛获奖，这也是提高子女的修养，子女小时候不理解，但一定终身受益。 第四点是我惊叹到导演居然在最后一刻安排将父亲关在小房间里。这一点对吉塔的成长太重要了，如果父亲在场，吉塔能赢，但这不是她自己，而是有她父亲的一半，她的意志还是父亲用来实现理想的一个附属。但是父亲被关在小黑屋里那一刻，吉塔变成了她自己，她在荧幕中完完全全活了起来，她赢的那一刻，她是在实践去做她自己。所以我看到父亲被关进去的那一刹那（虽然已经知道情节），还是深深舒了一口气，为吉塔感到高兴。 最后一点，是细细品味后，我惊讶到这部电影一切都是恰到好处。首先，这个故事的背景几乎没有只有印度人可以看懂的印度文化，里面表现出印度专有文化的几个镜头基本不用理解就可以完全明白。再说到这个故事，本身是一个励志故事，大概就是一个被所有人看不起的穷小子成功逆袭的路线，把故事背景换到中国，换到日本，甚至换到美国，都可以找到类似的题材。第三呢，这个电影虽然反映了印度的男女不平等、童婚、甚至是官员不作为等等问题，但都是点到为止，没有一丝一毫的多余，在最后吉塔击败白人选手，印度国歌响彻电影院的那一刹那，这些批判什么都不算，这部电影的主题是爱国！但又不脑残。电影的节奏安排也非常合理，在情节最紧张的时候，观众们都屏息凝神，而几乎每一个笑点，可以让从几岁到几十岁的人都会心一笑。特别是到了吉塔最后比赛的时候，拍摄得更是精妙。我扫视一下电影院，发现虽然大家都知道最后肯定会赢，但是眼神里都是紧张二字，在每一个得分点出现的时候，我看见旁边的姑娘更是激动得和屏幕里赛场中的观众一起鼓掌（要不是这里是电影院的话可能就要欢呼出来了）。一部电影，能做到这一点太难得了。 所以，这部电影这么火，并不是偶然，它是一部每一个细节都用心雕琢的好电影。 今天也是母亲节，这部片让我想起来老妈这么多年来对我的培养。 她和片中的父亲不一样，没有严厉的要求，更从没有将她的意志加在我的肩上。我从小到大，她是我的母亲，更是我的挚友。 老妈对我的教育方式虽然和片中父亲虽然完全不同，但有着相同的胸怀。宽松的环境反倒让我可以思考得更加深入，有机会去读书去接触他人。 这些都让我从侧面更加解我自己，知道自己应该去做什么，更明白自己在做什么，更可以为自己所做的事情负责。 所以我很庆幸，我（我想父母也是）早已经过了上文中所说的吉塔父亲被关进小黑屋的那一关。 再矫情的话我也说不出了，不过此刻确实非常想给老妈一个大大的拥抱。 最后的最后，附上几张看完电影后在学校中见到的如画一样的美景吧： <a href="http://blog.zhengzi.me/wp-content/uploads/2017/05/微信图片_20170515012923.jpg"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/05/微信图片_20170515012923-1024x768.jpg" alt=""></a>  <a href="http://blog.zhengzi.me/wp-content/uploads/2017/05/微信图片_20170515012914.jpg"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/05/微信图片_20170515012914-768x1024.jpg" alt=""></a> <a href="http://blog.zhengzi.me/wp-content/uploads/2017/05/微信图片_20170515013156.jpg"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/05/微信图片_20170515013156-1024x768.jpg" alt=""></a></p>

          
        
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://blog.zhengzi.me/2017/05/01/e8-b0-88-e5-8f-8a-e8-87-aa-e7-94-b1-e4-b8-8e-e7-be-8e-e7-9a-84-e7-90-86-e6-83-b3/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Jason Bian">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="政子的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/05/01/e8-b0-88-e5-8f-8a-e8-87-aa-e7-94-b1-e4-b8-8e-e7-be-8e-e7-9a-84-e7-90-86-e6-83-b3/" itemprop="url">
                  谈及自由与美的理想
                </a>
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              

              
                
              

              <time title="Created: 2017-05-01 23:19:24" itemprop="dateCreated datePublished" datetime="2017-05-01T23:19:24+08:00">2017-05-01</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Modified: 2018-08-21 17:49:42" itemprop="dateModified" datetime="2018-08-21T17:49:42+08:00">2018-08-21</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/随笔/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>这个周就要立夏了，在这个夏天我要战胜它，也战胜自己。 周末和老弟遛弯聊天，他跟我谈及一个严肃而单纯的问题：既然毒品能给人带来快感，那为什么不人人都去吸毒呢？ 我假装成一副胸有成竹的模样，“好问题！不过先别讲这个，我要和你谈谈音乐。我还记得上次和你去国家大剧院听新年音乐会时候你的表现。” 为什么谈音乐呢？我无非是希望引导他去认识到音乐之美，而审美判断是“无利害而生愉悦”，从而认识到有比毒品更自由的获得快瑟之感的方式——艺术或者说是道德。 我几乎成功了。 “那么这种愉悦和那种愉悦有何区别？”这个话题绕不开道德。 “而且你刚刚在讲，美的理想和道德的理念是同一的。那么假设一个人没有（像我们世人一样的）道德，那么他是不是也无法感受到艺术之美，那么他只能从毒品之类的东西中获得物质的快感？而凭什么人人都有这样的道德呢？” 我再令他去想为什么国家和法律如此“暴力”：道德次序的维持需要暴力，暴力保证了次序，也保证了减少暴力。所以毒品和问题需要暴力解决。 “但是，道德又有什么意义呢？你用暴力去维系道德又有什么意义呢？” “因为人需要自由。人向往自由。音乐可以让人获得自由，道德可以，而毒品不行！” 但自由又有什么意义呢？什么才是自由呢？ 我有些歇斯底里，不过在五月份，话题也总是绕不开它。 “你说向往自由，但是佛陀获得了自由，所以他领会到了空。但是空，不会太无聊点了么？” “所以你想要的意义不就是来自于欲望，这能让你不那么无聊。” “但是欲望和自由是不是就矛盾了？” 所以人生大概就是痛苦的吧。</p>

          
        
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://blog.zhengzi.me/2017/04/11/p4-e7-9b-b8-e5-85-b3-e5-ba-94-e7-94-a8-e7-ae-80-e4-bb-8b/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Jason Bian">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="政子的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/04/11/p4-e7-9b-b8-e5-85-b3-e5-ba-94-e7-94-a8-e7-ae-80-e4-bb-8b/" itemprop="url">
                  P4相关应用简介
                </a>
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              

              
                
              

              <time title="Created: 2017-04-11 09:56:37" itemprop="dateCreated datePublished" datetime="2017-04-11T09:56:37+08:00">2017-04-11</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Modified: 2018-08-21 17:49:42" itemprop="dateModified" datetime="2018-08-21T17:49:42+08:00">2018-08-21</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/P4/" itemprop="url" rel="index"><span itemprop="name">P4</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="INT"><a href="#INT" class="headerlink" title="INT"></a>INT</h2><p>In-band Network Telemetry</p>
<h3 id="Specification"><a href="#Specification" class="headerlink" title="Specification"></a>Specification</h3><p><a href="http://p4.org/wp-content/uploads/fixed/INT/INT-current-spec.pdf" target="_blank" rel="noopener">http://p4.org/wp-content/uploads/fixed/INT/INT-current-spec.pdf</a></p>
<h3 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h3><p>INT是一种用来在数据平面上采集和报告网络状态的框架，它不需要控制平面的任何干预或支持。在INT的模型里，设备发出的数据包会包含“遥测”的报头字段。这些字段会告诉兼容INT的设备在需要转发包的时候需要收集哪些信息，并将其写入包中。</p>
<p>INT流量源（比如应用程序，端主机网络栈，NIC，虚拟管理程序或者发送ToR）等可以将指令嵌入在正常的数据包或者特殊的探测包中。类似地，INT流量接收器可以取到（并有选择地报告）这些指令所收集到的结果。INT流量收集器可以在转发的同时精确地利用从数据包里观察到的信息来监视数据平面的状态。</p>
<h3 id="举例说明可以收集并处理的信息"><a href="#举例说明可以收集并处理的信息" class="headerlink" title="举例说明可以收集并处理的信息"></a>举例说明可以收集并处理的信息</h3><ul>
<li>OAM：可以只简单地将收集到的网络状态编码（可以使用元数据，或者进行简单的清洗或压缩），并且将其发送给额外的控制器。</li>
<li>实时控制或者反馈环路：INT流量接收器可以编码数据平面的信息并将控制信息反馈给流量源，流量源可以利用这些数据调整流量工程或者数据包的转发（比如进行显式的拥塞控制）。</li>
<li>网络事件探测：如果收集到的路径信息表明需要立即注意或解决的状况（比如严重的拥塞或者数据平面被破坏，INT流量接收器可以立刻报告一个网络事件，在集中式或者分布式的网络中形成一个控制回路）。</li>
</ul>
<h3 id="INT体系结构式通用的，因此可以支持一些有趣的高层应用"><a href="#INT体系结构式通用的，因此可以支持一些有趣的高层应用" class="headerlink" title="INT体系结构式通用的，因此可以支持一些有趣的高层应用"></a>INT体系结构式通用的，因此可以支持一些有趣的高层应用</h3><p>比如：</p>
<ul>
<li>网络故障排除：L2跟踪路由、微突发事件探测、数据包历史、轨迹采样</li>
<li>高级拥塞控制：RCP、XCP、TIMELY</li>
<li>高级路由：利用率感知路由（例如：CONGA）</li>
<li>网络数据平面验证</li>
</ul>
<h3 id="可以监控的范围"><a href="#可以监控的范围" class="headerlink" title="可以监控的范围"></a>可以监控的范围</h3><ul>
<li>交换机级别的信息：交换机ID</li>
<li>入口信息：入口ID，包进入时间</li>
<li>出口信息：出口ID，单跳延迟，出口链路利用率</li>
<li>缓存信息：队列使用率，队列拥塞状态</li>
</ul>
<h3 id="INT包封装"><a href="#INT包封装" class="headerlink" title="INT包封装"></a>INT包封装</h3><p>INT头不在特定位置封装，INT报头可以作为任何包的选项或者有效载荷插入其中，唯一的要求是有足够的空间承载INT信息，并且INT的源和接收器需要达成一致。</p>
<p>一些可能的位置：</p>
<ul>
<li>INT over VXLAN（作为一个VXLAN的选项，每个GPE扩展）</li>
<li>INT over Geneve（作为一个Geneve选项）</li>
<li>INT over NSH（作为一个NSH选项）</li>
<li>INT over TCP（作为一个TCP选项或者载荷）</li>
<li>INT over UDP（作为一个载荷）</li>
</ul>
<h3 id="INT元数据头格式"><a href="#INT元数据头格式" class="headerlink" title="INT元数据头格式"></a>INT元数据头格式</h3><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/e56578017ef126783d76dcbc0cb9e0e3.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/e56578017ef126783d76dcbc0cb9e0e3.png" alt=""></a></p>
<ul>
<li>每一个INT元数据头长度为8B，每个元数据经常被以4B长度编码。</li>
<li>INT指令被编码在一个16bit的指令区域，包括：Switch ID, Ingress Port ID, Hop latency, Queue occupancy, Ingress timestamp, Egress port ID, Queue congestion status, Egress port TX utilization</li>
<li>沿着支持INT的路径，每个INT设备都会根据报头的指令添加自己的元数据值。</li>
<li>添加元数据的时候，每个设备都必须在已经被上游设备添加的元数据之前添加信息，遇到不能添加或者其他问题，会有一些错误处理的机制。每个元数据都包含栈底比特确认是否为最后一个元素。</li>
</ul>
<h3 id="一个在Geneve选项中添加INT包的例子（示意图）"><a href="#一个在Geneve选项中添加INT包的例子（示意图）" class="headerlink" title="一个在Geneve选项中添加INT包的例子（示意图）"></a>一个在Geneve选项中添加INT包的例子（示意图）</h3><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/558cb7565278c11c41684b471445ff52.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/558cb7565278c11c41684b471445ff52.png" alt=""></a></p>
<h2 id="HULA"><a href="#HULA" class="headerlink" title="HULA"></a>HULA</h2><p>Hop-by-hop Utilization-aware Load Balancing Architecture</p>
<h3 id="Specification-1"><a href="#Specification-1" class="headerlink" title="Specification"></a>Specification</h3><p>Scalable Load Balancing Using Programmable Data Planes</p>
<p><a href="http://delivery.acm.org/10.1145/2900000/2890968/a10-katta.pdf" target="_blank" rel="noopener">http://delivery.acm.org/10.1145/2900000/2890968/a10-katta.pdf</a></p>
<h3 id="介绍-1"><a href="#介绍-1" class="headerlink" title="介绍"></a>介绍</h3><p>现在的数据中心网络有多路拓扑（如Fat-Tree和Leaf-Spine）来提供大的平分带宽。这些拓扑都有大量的多路径，在两个终结点之间有许多路由。有效的数据平面多路流量均衡是有效利用带宽资源的一个重点。最常用的数据平面负载均衡的技术是ECMP，它将每个流都随机分割给一个或多个路径。但是如果两个比较大的流量被分配给同一个路径的话，ECMP的性能将会下降。CONGA使用链路利用率信息，克服了ECMP的不足。但是CONGA是利用硬件进行流量均衡的，一旦部署算法将不能更改，而且设备内存有限，CONGA并不能跟踪所有拓扑的信息，所以这阻碍了CONGA的拓展性。</p>
<p>HULA比CONGA更加灵活，首先HULA只需要下一跳的信息，并且HULA是为可编程交换机所设计的。</p>
<p>HULA使用特殊的探针（与数据包有所区分）来聚合整体的链路利用率信息。这些探针周期性地在网络中传输，并且覆盖了所有要进行负载均衡的路径。这些信息被处理并存放在每个交换机的一个表中。这个表给出了通往目的地的最佳下一跳目标。随后，每个交换机利用它所掌握的最佳的下游路径（最佳路径是所有路径的最大链路延迟中最小的那一个）来更新探针，并且发送给上游路由。这就像<strong>距离向量协议</strong>那样使得最佳路径在整个网络中传播。为了避免数据包乱序，HULA使用flowlet作为均衡的粒度。</p>
<h3 id="HULA的特性：可伸缩，主动式，自适应、可编程"><a href="#HULA的特性：可伸缩，主动式，自适应、可编程" class="headerlink" title="HULA的特性：可伸缩，主动式，自适应、可编程"></a>HULA的特性：可伸缩，主动式，自适应、可编程</h3><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/59a740260228b99943d1c44bedddaba1.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/59a740260228b99943d1c44bedddaba1.png" alt=""></a></p>
<h3 id="简单细节"><a href="#简单细节" class="headerlink" title="简单细节"></a>简单细节</h3><p>每一个ToR在所有的上传链路中给数据中心网络发送HULA探针。探针可以被ToR的CPU、交换机的数据平面或者连接到ToR的服务器发送。这些探针被定时周期发送，一旦收到探针，它将会被转发到下游的所有ToR和上游所有的Spine中，但保证不会形成环路。一旦探针到了另一端的ToR，它的转发将会结束。控制平面会在数据平面设置多播组来使得这些探针可以被复制。</p>
<p>一个HULA探针包包含了一个HULA头和正常的以太网头以及IP头。HULA头包含torID和minUtil两个字段。每个交换机为每个端口维持一个利用率估计值。一个交换机在将探针转发给其他交换机之前使用探针头和自身的链路利用率信息升级交换机的状态。</p>
<p>每个交换机维持一个最佳利用率的表和一个最佳下一跳表。这两个表都使用Tor ID进行索引。最佳利用率（pathUtil）表的每一行给出了从这个交换机到目的地ToR的最佳路径的链路利用率信息。最佳下一跳（bestHop）表的每一行是在最佳利用率表中到达目的ToR可以有最佳链路利用的下一跳交换机。</p>
<p>在计算最小的最大链路利用率的时候用了类似距离向量算法的流程。</p>
<p>交换机会保持现在的最佳下一跳表并在携带有使得其更新为更好的下一跳的探针到达时更新它。</p>
<h3 id="HULA在高负载时的表现"><a href="#HULA在高负载时的表现" class="headerlink" title="HULA在高负载时的表现"></a>HULA在高负载时的表现<a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/2dd159f7a72ba79cd272a31b605a4156.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/2dd159f7a72ba79cd272a31b605a4156.png" alt=""></a></h3>
          
        
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://blog.zhengzi.me/2017/04/08/p4-e8-99-9a-e6-8b-9f-e5-8c-96-e6-95-b0-e6-8d-ae-e5-b9-b3-e9-9d-a2/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Jason Bian">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="政子的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/04/08/p4-e8-99-9a-e6-8b-9f-e5-8c-96-e6-95-b0-e6-8d-ae-e5-b9-b3-e9-9d-a2/" itemprop="url">
                  译文——P4虚拟化数据平面
                </a>
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              

              
                
              

              <time title="Created: 2017-04-08 10:44:45" itemprop="dateCreated datePublished" datetime="2017-04-08T10:44:45+08:00">2017-04-08</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Modified: 2018-08-21 17:49:42" itemprop="dateModified" datetime="2018-08-21T17:49:42+08:00">2018-08-21</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/P4/" itemprop="url" rel="index"><span itemprop="name">P4</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>现在SDN已经有了在数据平面的编程能力，这使得网络设备（包括硬件）可以被重新编程以解析自己定制的协议和执行定制的功能。 但是，数据平面的编程能力还没有发挥最大的潜能，它依旧不完善，而且在不断增长的软硬件中提供可编程能力是有很大形成碎片的风险。如果使用虚拟化方案可以解决以上两个问题。 <img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/200a1633ec0f73c741ff0c7d4f371565.jpg" alt="">  OpenFlow已经为网络的控制平面提供了一个标准的可编程能力，并且在网络管理者寻找更加的自由和灵活的方案候起了重要的作用。 但是，它并没有使的数据平面有良好的可编程能力，数据平面依旧只能使用在OpenFlow的协议规范中被定义好的协议。如果OpenFlow需要支持较新的方案，那么OpenFlow的规范就要一直被扩展。 一个真正的数据平面按应该不被这些束缚，它应该允许管理员重新配置数据平面以完全适应自己定制的协议中的语法和语义。最近在可重配置的匹配表（reconfigurable match table，RMT）中的工作在体系结构上已经证明了可编程数据平面，即使在ASIC的硬件中也是可行的。 这个结果使得像P4这样的领域专用语言使得这些可编程数据平面可简单地以一个统一的方式在多种交换机上部署（比如基于RMT的ASIC、FPGA为基础的交换机、像PISCES一样的软件交换机、behavior model和在边缘服务器上的网络数据平面）。</p>
<h1 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h1><p>一般来讲，每一个P4兼容设备提供的可编程数据平面表示一种网络环境。 每一个P4的程序定义了：</p>
<ul>
<li>在流量被解析时的协议头的集合和与之相符合状态机</li>
<li>在流量被处理时的匹配-执行表</li>
</ul>
<p>为了支持不同的客户的类型和为复杂的包处理而灵活地组成虚拟方法，在多数情况下，操作者希望给定的网络设备可以有不止一个环境，即使只有一个物理的数据平面。 一个解决方法就是虚拟化。虚拟化可以虚拟出多个数据平面并且使用时会比多个设备更加流畅和方便。比如，借助虚拟化，我么可以同时在备上通过不同的配置部署多个网络功能，它允许：</p>
<ul>
<li>网络切片：隔离一些客户或者设备，这使得网络更加的现代和安全。每一个切面（也就是每一个网络环境）可以因为支持协议类型和功能的不同而完全不同。</li>
<li>网络快照：当一个配置每次到达的时候，存储多个网络或者设备的配置，并且提供配置之间的快速切换。</li>
<li>设备内部的虚拟网络，提供了针对以下两者的解决方案：<ul>
<li>包处理程序的复杂模块设计，支持模块化开发</li>
<li>在交换机上支持多用户，并且使用可控的方法为他们提供服务</li>
</ul>
</li>
<li>提供标准的高层功能，比如程序分析，流量监控和其他功能</li>
</ul>
<p>这些环境都需要隔离机来制止一个程序对另一个程序产生的威胁并保护设备避免其潜在危险的程序的威胁。 使用虚拟化，可以使得物理上单一的数据平面支持逻辑上的多种网络环境。那么，是不是可以有一种使用纯P4语言实现的通用虚拟化框架呢？如何使用一个用户级别的程序来实现虚拟化？是否可以使用一个特殊设计的具有模拟其他P4程序的能力的P4程序？ 这样可以动态地支持虚拟化，而且可以在不中断现有的网络设备的情况下部署和重新配置，它具有很强的便携性。 HyPer4使用软件的方式拓展了P4语言，使得支持P4语言的设备可以具有如下功能：</p>
<ul>
<li>可以在逻辑上存储多个P4程序并且同时运行它们（作为网络切片）或者热切换的快照</li>
<li>在每一个程序之间可以形成一个虚拟网络（支持程序不同部分和或者多租户服务交互）</li>
<li>HyPer4可以在运行时修改程序集和改变他们的虚拟网络连接而不用中断现在正在运行的程序。</li>
<li>可以兼容ASCI的硬件。</li>
</ul>
<h1 id="运行环境"><a href="#运行环境" class="headerlink" title="运行环境"></a>运行环境</h1><h2 id="P4语言运行环境简介"><a href="#P4语言运行环境简介" class="headerlink" title="P4语言运行环境简介"></a>P4语言运行环境简介</h2><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/4b417aa6e68d2cc0b536f67705ecd7ac.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/4b417aa6e68d2cc0b536f67705ecd7ac.png" alt=""></a> 上图描述了典型P4程序的编译过程，它分为两步：</p>
<ol>
<li>前端编译器将P4源代码编译为高级中间表示（high-level intermediate representation, HLIR）</li>
<li>后端编译器将HLIR转换为特定目标设备的形式（比如JSON或者二进制代码）。 比如现在P4编译器后端提供了p4c-bmv2，它会将HLIR转化为Barefoot Network的bmv2软件交换机可以使用的JSON文件；SDNet可以将其编译至Xininx FPGA的代码；LLVM_P4和P4-to-EBPF可以将其转换为Linux网络平面使用的EBPF程序。</li>
</ol>
<p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/a99988c3ff3d71a695285db1b013bc2a.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/a99988c3ff3d71a695285db1b013bc2a.png" alt=""></a> 上图左边部分描述了P4设备开始配置的过程。首先，用户会编译P4的代码，然后将二进制代码（或者其等价形式）装载进P4兼容的设备中。 上图右边部分描述了在二进制代码被装在进入P4设备后，设备就可以在运行时接受和代码兼容的控制器的指令。</p>
<h2 id="HyPer4运行环境"><a href="#HyPer4运行环境" class="headerlink" title="HyPer4运行环境"></a>HyPer4运行环境</h2><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/3cce2c00c7a205476c1a7b9571801833.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/3cce2c00c7a205476c1a7b9571801833.png" alt=""></a> 上图分为三部分：</p>
<ol>
<li>左边部分演示了使用HyPer4环境部署和载入foo.p4代码的过程，和原生P4环境一样，在P4设备中生成了一个HyPer4的运行时环境，但是这时的运行时环境只是具有执行的能力，并没有可执行的表。</li>
<li>中间部分展示了如何将普通的P4程序通过HyPer4编译器编译为实体表然后载入运行时环境。</li>
<li>右边部分展示了为了不修改现有的控制器，HyPer4使用了一个数据平面管理单元（Data Plane Mangagement Unit, DPMU）来作为控制器和交换机之间的代理。它可以将对于原有P4代码的虚拟表的操作转换为HyPer4表的操作。</li>
</ol>
<h1 id="几个例子"><a href="#几个例子" class="headerlink" title="几个例子"></a>几个例子</h1><p>已实现的代码片段</p>
<ul>
<li>一个二层以太网交换机</li>
<li>一个IPv4路由器</li>
<li>一个代表交换机上的IPv4主机回复ARP请求的ARP代理</li>
<li>一个可以过滤IPv4、TCP和UDP源和目的的防火墙</li>
</ul>
<p>使用这几个简单的P4代码片段，有以下三个例子来说明可编程数据平面</p>
<h2 id="快照和简单地模块化"><a href="#快照和简单地模块化" class="headerlink" title="快照和简单地模块化"></a>快照和简单地模块化</h2><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/4f5df35aa5b423d6c4103401a3199db5.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/4f5df35aa5b423d6c4103401a3199db5.png" alt=""></a> 上图是一个网络快照和模块化的示例。这个网络包含三个已经连接的P4设备：s1、s2和s3，每一个设备上都在运行HyPer4程序。两个主机h1、h2和s1连接，另外两个主机h3、h4和s3连接。 最开始，HyPer4的表项是空的，而且设备被分为不同的功能。我们接着将HyPer的表实体下发给每个设备，使得每个设备逻辑上存储了所有的程序，这三个程序可以通过网络配置进行切换。 在开始的配置中，s1和s3分别运行arp代理，s2运行二层交换。在上图的s1和s3中，虚线框中的A代表arp代理功能，在s2中，虚线框中的A代表二层交换功能。 在第二个配置中，s1和s3都运行二层交换，s2运行防火墙。这些功能都被标记为B。 在第三个配置中，s1和s3都运行了和第二个配置一样的二层交换，s2运行了一个复合的程序，这些被标记为C。当流量第一次到达s2的时候，首先被arp代理处理，然后其他的流量会被传送到s2中的下一个虚拟功能——一个防火墙。并且任何可以通过防火墙的流量都会被一个路由应用处理。 同时，每个虚拟功能的流表也会被下发给每一个运行HyPer4的设备：</p>
<ul>
<li>二层交换机的MAC和目的端口对</li>
<li>arp代理的IPv4和MAC对</li>
<li>路由器的IPv4目的地址和下一跳IP和MAC地址对</li>
<li>防火墙对于TCP特定端口的过滤规则</li>
</ul>
<p>每次在一台设备中只有一个配置被激活。切换配置的时候需要控制器发送一个流表项。</p>
<h2 id="网络切片和模块化"><a href="#网络切片和模块化" class="headerlink" title="网络切片和模块化"></a>网络切片和模块化</h2><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/532cbd33d406c7db338d63ad47096bae.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/532cbd33d406c7db338d63ad47096bae.png" alt=""></a> 上图描述了一个运行HyPer4的P4设备s1和4个连接它主机h1、h2、h3、h4。 s3、s4的IP地址和子网掩码已经被设置，所以他们在不同的逻辑网络内。 使用HyPer4来将s1进行切片，使得连接h1和h2的端口1和2被分配到一个逻辑设备，连接h3和h4的端口3和4被分配到另一个逻辑设备。 在一开始，s1中HyPer4的表项是空的，并且s1已经被分为许多功能。 然后给HyPer4下流表，使得s1逻辑上存储三个程序：</p>
<ul>
<li>在1和2端口上的流量被一个二层交换机处理</li>
<li>在4和3端口上的流量首先被一个防火墙处理，然后通过防火墙的流量被一个路由器处理</li>
</ul>
<p>同时，也需要针对二层交换机（MAC地址和出端口对），防火墙（过滤TCP特定端口的流量）和路由器（IPv4目的地址和下一跳IP和MAC地址对）下流表。</p>
<h2 id="虚拟网络"><a href="#虚拟网络" class="headerlink" title="虚拟网络"></a>虚拟网络</h2><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/a9df91177d61c0229967ea447fcad429.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/a9df91177d61c0229967ea447fcad429.png" alt=""></a> 上图描述了虚拟设备间的虚拟网络。这个网络包含了一个有h1、h2、h3、h4四个主机连接的单一的P4设备s1。每个主机都被分配到了不同的网络。 在S1上被载入了8段程序，创立了8个虚拟设备：</p>
<ul>
<li>在h1上的一个路由器r1和一个防火墙f1</li>
<li>在h2上的一个路由器r2和一个防火墙f2</li>
<li>在h3上的一个路由器r3</li>
<li>在h4上的一个路由器r4</li>
<li>连接内部网络的两个二层交换机l2_s1和l2_s2</li>
</ul>
<p>当为每一个设备下流表以后，这个示例演示了如何使得s1通过HyPer4支持希望为每个人服务但是又需要有安全控制的多租户方案。</p>
<h1 id="HyPer4系统的设计"><a href="#HyPer4系统的设计" class="headerlink" title="HyPer4系统的设计"></a>HyPer4系统的设计</h1><h2 id="总览"><a href="#总览" class="headerlink" title="总览"></a>总览</h2><p>在高层上来看，HyPer4具有一个运行环境，一个编译器和一个数据平面管理单元（data plane management unit，DPMU）。 一个P4程序定义了包处理的结构。当执行的时候，以匹配表形式出现的运行时状态（可随时改变）会影响一个包会如何被包处理结构处理。 Hyper4定义了一个足够通用的结构，这个结构可以允许状态以任意的途径改变，并影响数据包处理的流程。 <a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/0a78f120fe9804e23c512a79c9e6fe43.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/0a78f120fe9804e23c512a79c9e6fe43.png" alt=""></a> 上图描述了HyPer4运行环境的概览。 HyPer4分为三个阶段</p>
<ol>
<li>解析和设置阶段接受数据包并且使用一个模拟的P4程序来为将数据包设置为一个明确的HyPer4状态</li>
<li>HyPer4模拟了目标程序的匹配-执行状态序列</li>
<li>egress阶段处理任意的egress专有的的原始操作并且准备传输</li>
</ol>
<h3 id="可编程的解析器"><a href="#可编程的解析器" class="headerlink" title="可编程的解析器"></a>可编程的解析器</h3><p>运行环境必须可以解析在包中匹配到的任意字节的数据，它通过遍历一棵分析树来达到这个目的。在一棵树中每一个节点解析整体需求的一部分需要并且在一个元数据分支上的字段<code>numbytes_to_extract</code>存储这些需求。 框架在ingres pipeline的设置阶段设置了解析器的一些属性，如果需要，它会将包返回至ingress pipeline。 特别地，<code>numbytes_to_extract</code>依赖于虚拟设备以及和它有关的包。 框架也使用了P4的resubmit操作来使得包被重新送回解析器（如果需要的话）。 resubmit操作非常强大，因为可以将需要保留他们的值的字段列表传给它（比如<code>numbytes_to_extract</code>）。最终，解析器提取了一个字节栈，resubmit的操作可以在一个包含一个虚拟设备可能需要处理的许多包头的包上被重复调用多次。</p>
<h3 id="字段描述"><a href="#字段描述" class="headerlink" title="字段描述"></a>字段描述</h3><p>框架使用了非常广泛的元数据字段来表示虚拟设备需要使用的字段列表。 框架也定义了一个逻辑上存储所有被从包中解析出的数据（被解析器解析出的字节栈）的字段，并且另一个字段会被用来表示虚拟设备中所有的元数据字段。</p>
<h3 id="匹配"><a href="#匹配" class="headerlink" title="匹配"></a>匹配</h3><p>任意的P4程序匹配任意的字段。HyPer4的任务是以将一个大的源数据字段的相关部分隔离开的方法支持任意的字段，并将其用以表示一个P4程序的被定义好的字段。 HyPer4使用了非常多的P4的三元组匹配机制对这种模式进行支持，它允许在匹配值的时候一同提供表中匹配实体和掩码，这些掩码被用于在和匹配的数据比较之前确定匹配的区域。</p>
<h3 id="执行"><a href="#执行" class="headerlink" title="执行"></a>执行</h3><p>匹配在P4程序中会触发可能是复杂的原始操作集合的执行过程。 HyPer4为每一个支持的P4原始操作提供了一套共同执行需要的行为的表。 简单来说，框架使用了一个元数据字段的集合在每个包处理阶段的必要时重定向HyPer4的控制流。 各种HyPer4中不同的匹配-执行阶段会读取（匹配），写入，或者读写这些元数据字段。 用提供这些表的实体来确定被用于读取或者写入这些确定的值，使得操作者可以调用相关HyPer4提供的需要执行任意行为的方法。</p>
<h3 id="虚拟网络-1"><a href="#虚拟网络-1" class="headerlink" title="虚拟网络"></a>虚拟网络</h3><p>HyPer4依赖P4的recirculate原始操作将包从一个设备传送到另一个设备。这个操作会在完成egress pipeline以后标记一个会被重新发回的包。 它允许将一个字段列表作为参数传入。当包重新在解析器出现的时候，这个列表里所有的字段将会保持它原有的值。 HyPer4结构依赖于一般的匹配-执行阶段的概念。HyPer4的状态可以决定应该进行哪一种匹配操作和进行每一种原始操作的参数。为了模拟其他的P4程序，HyPer4需要根据被仿真的目的程序改变HyPer4的状态，进而将其被转换成对于表的操作。 通过将P4程序表示成状态，HyPer4可以支持P4程序的实时更新。</p>
<h2 id="解析器"><a href="#解析器" class="headerlink" title="解析器"></a>解析器</h2><p>P4程序解析器的规则是将一个包前N比特的结构鉴别为一系列具有相关标签的比特字段。这些被打标签的比特字段也可以被称为一个包的“Parsered Representation（被解析的表示）”。 程序员定义了包头的类型，其中指出了名字、宽度和在比特区域中的位置，并且还声明了当解析包中比特的时候这些类型所定义的包实例。 为了解析一个包头，要做的是添加根据包的类型被结构化和命名的一个比特域的集合，并将其转变为Parsered Representation。 解析器决定那些包头应该被解析的方法是根据包中的数据或者元数据中一些字段的数据标记解析图的分支。 HyPer4必须用可以在运行时重新配置的方法来解析足够数量的的数据来达到模拟其他P4程序的需求。 框架定义了一个有一字节宽度单一字段的包头类型，并且声明了一个这个类型的数组来适应从包中解析出的变化的字节长度。 同时，框架也定义了一个元数据字段（比如<code>numbytes_to_extract</code>）。 一旦收到了一个包，解析器会验证这些字段。 数值为0表明它还没有为引导解析过程做好准备。在这种情况下，一个默认长度的字节会被解析（一般来说是20字节），并且控制流被重定向到一个初始化方法中去（上图的setup -a环节），如果有必要，它会更新<code>numbytes_to_extract</code>并且将包重新提交。被重新提交的包会重新回到解析器，但是这次<code>numbytes_to_extract</code>是一个有意义的值。 HyPer4遍历了在这个区域的解析树中可以解析的每个部分的分支。 在完成解析以后，HyPer4将所有被解析的字节连接到一起。在整个剩下的处理流程中，框架使用一个非常大的元数据字段来表示这些被解析的字段。 设置函数（上图的setup -b）接着配置包处理的流程。 特别地，这个函数设置一个指示了被仿真的程序在HyPer4中可能需要执行的元数据字段。 它也设置了另一个字段去表明哪一个表应该是最初被执行的（根据被模拟的程序中匹配到的类别的匹配-执行阶段），并将其作为HyPer4的匹配-执行阶段。</p>
<h2 id="匹配-执行"><a href="#匹配-执行" class="headerlink" title="匹配-执行"></a>匹配-执行</h2><p>每一个被模拟的匹配-执行阶段都需要一些HyPer4的表：一个去执行匹配，另外三个元操作的表去执行相应的表匹配功能。 为了执行匹配，框架定义了一个匹配类型（精确匹配，三元组匹配，验证有效性）的所有组合和每个阶段所有数据类型的表。 HyPer4使用元数据的<code>next_table</code>的字段中进行分支（在初始化设置阶段或者在在上述的匹配-执行过程的结尾设置）。通过这个设置，程序将会执行正确的表。 精确匹配而不是解析包中的数据是一种匹配类型，在这种情况下，HyPer4使用一个三元组而非单一数据匹配，使用一个非常宽的字段来表示提取出的数据包。 三元组匹配在分离这个字段中和匹配有关的比特时非常有用（比如去鉴别在<code>foo.p4</code>中被定义的哪个字段参与了匹配）。 一般来讲，三元组匹配帮助模拟许多匹配类型而不是许多数据类型，因为它允许在运行时表项提供比特掩码（尽管它在TCAM单元中的能耗会很显著）。 在每一种情况下，一个匹配触发一个动作，并设置各种元数据字段。这些字段一定会有一个到达控制函数的分支来表达第一个被模拟的过程的原始操作。 执行一个原始操作包含了至少三个表，一个设置原始操作的阶段，另一个执行原始操作，最后一个进行状态包含了表明HyPer4的操作（以及匹配-执行阶段）是否完成，或者更多的原始操作需要被执行。</p>
<h2 id="逆解析"><a href="#逆解析" class="headerlink" title="逆解析"></a>逆解析</h2><p>在P4中，在整个包处理的过程中都可能会改变这个包的被解析后的表示，不仅包括包头字段的值，也包括这个包本身的结构（这个包的包头可能会被删除或添加）。因此，为了鉴别出来序列的头部，然后序列化进行传输，逆解析是一个必须的步骤。 但是逆解析器在P4的代码中并没有出现，而是将一个具有特殊构建的解析器反过来当作逆解析器。 因为HyPer4在整个包处理的过程中使用了一个元数据字段当作Parsered Representation的代理，所以在最后egress pipeline的过程中，必须将Parsered Representation进行回写成原来的形式为包的逆解析作准备。 Parsered Representation包含了一个单字节的包头的栈，所以这个准备过程包含了重复的为代理的元数据字段加掩码的过程，将最低位的字节拷贝到栈中的下一个头部，并且将其余数据字段向右移位一个字节。</p>
<h2 id="隔离"><a href="#隔离" class="headerlink" title="隔离"></a>隔离</h2><p>在现在框架的设计中将每个程序分离，它保护了一个程序的代码不被另一个程序重写。现在框架也支持内存的隔离。 代码隔离是在编译的时候给每一个程序指派一个独立的标识数来解决的（它可以是P4代码的哈希值或者是在编译器下载程序的时候人为决定）。 当收到一个包的时候，一些操作者可以控制的条件（比如进入端口，时间，网络安全状态或者一个包中包含的值）确定哪个程序应该去处理它，相应的元数据字段会被设置成为相应的程序ID。 这个字段是每一个环境中的匹配-执行的模拟表的匹配字段之一，并且它也在相同的共享的物理表中将一个程序的表项同另一个程序分离开。 框架将一个模拟的程序看作一个虚拟设备。这个程序的ID在功能上很类似于VLAN ID，尽管分配一个程序ID的机制会更加的灵活。 DPMU监视器需要给虚拟设备添加表项并且确保对于请求者所请求的程序ID是被许可的。 同时，DPMU可以强行限制每个虚拟设备可用的表项的数量，部分地协助完成内存隔离。另外内存隔离的需求使用一个内存状态对象（计数器，量表和寄存器）作为协助。 HyPer4设计要求预分配这些对象，这些对象中的设置的数量要和虚拟设备中的数量是相等的。这是HyPer4一起将这些集合分配给虚拟设备时的规则。 CPU隔离在这里的意义是没有程序执行的动作不能在一个时钟周期中被完成。如果一个虚拟设备的操作没有满足上述要求，那么任何一个超时的包处理都会被停止，并且它后面的包也都会被延迟处理（可能会属于其他的虚拟设备）。但是现在的版本还没有实现这个功能。 输入缓存区是另一个可能使得虚拟设备之间的连接产生干扰的资源。在现在的系统设计中，一个虚拟设备可能使用原始操作重复触发把包发回给输入缓存的操作。这就可能使得其他的包无法进入缓存区。其他的包可能来自于外部的链接或者内部其他设备或者同样是被回发的操作。 一个解决这个问题的办法是提供一个阈值，如果进入输入缓存区的次数超过阈值，则这个包将会被丢弃。</p>
<h2 id="虚拟网络-2"><a href="#虚拟网络-2" class="headerlink" title="虚拟网络"></a>虚拟网络</h2><p>HyPer4被设计用于在环境中控制虚拟设备间的流量交换的虚拟网络。 框架创建带有唯一ID的虚拟端口并且将它分配给虚拟设备。这些虚拟端口可以被直接映射到物理端口上面，也可以将他们连接到另一端也是另一个虚拟设备的虚拟链路。 对于确定发送到其他虚拟设备的包，HyPer4在改变其程序ID以后使用<code>recirculate</code>的原始操作将其发送回解析器。 框架使用P4的<code>clone</code>和<code>recirculate</code>支持了虚拟多播。简要地说，程序的ID根据可编程的队列更新.接着一个包的复制被送去解析器并且最终被相关联的设备处理。其他的复制被送到egress pipeline的起始处，程序ID用作循环计数器，并且一旦到达多播序列的末尾，就会触发分组丢弃。</p>
<h2 id="设计结果"><a href="#设计结果" class="headerlink" title="设计结果"></a>设计结果</h2><ol>
<li>HyPer4使用三元组匹配来模拟各种的匹配类型而不是任意的数据字段，增加了TCAM的压力。这导致了能耗的增加以及在当前硬件上HyPer4的潜在TCAM障碍。</li>
<li>为了使得HyPer4可以来模拟来自一个行为集合中任意最大长度为K的的序列的行为，框架源代码必须声明K个执行从集合中给定的行为的表的复制。这是因为P4限制了在处理一个特定的包的时候使用一个表超过一次。P4的这种设计选择对于兼容硬件体系结构（由于物理写入约束和数据包处理算法对于顺序的依赖而选择使用在一条管道里面使用连接表而非使用纵横开关，比如RMT）来说是明智的，</li>
<li>使用重新提交原始操作来允许动态可编程解析器来减少吞吐量。HyPer4可以避免这些的P4设备重复的的重新提交直到到达某个最大的数目导致不再有空间可用的解析器异常。有趣的是，协议透明转发和P4不同，它有一种根据需求解析的机制，也可以消除HyPer4对于重新提交的需要。虚拟网络的recirculation也引起了吞吐量的损失，但是这是把一个物理设备虚拟成多个设备的自然结果。</li>
<li>HyPer4可以发送时间上完全不同于它有效接收的数据包，而标准的P4程序通常不是这样的。P4通过使用.p4代码中的解析器函数执行的相同的路径表示和剩余的数据包序列化解析的表示。这样做的结果就是P4程序只能发送和它能解析的结构一致的包。但是HyPer4将大多数的解析逻辑放在了ingress pipeline中，并且实际上HyPer4的解析路径简单地以一定长度的字节表达而没有更高层的结构。这样，HyPer4使得传统P4的限制被终结，不论是好是坏。</li>
</ol>
<h1 id="实践"><a href="#实践" class="headerlink" title="实践"></a>实践</h1><p>这个章节提供了关于实践的一些细节，所有的源码都可以在<a href="https://gitlab.flux.utah.edu/hp4/src.git" target="_blank" rel="noopener">这个git仓库</a>中访问到。</p>
<h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><p>HyPer4必须声明一份执行特定行为的表的拷贝，它们只在名字上不同，这样每一份拷贝都可以在一个行为序列的任何一个部分出现。这导致了一个有许多功能上冗余代码和庞大的代码基数。 比如，在HyPer4的源码中一定可以找到两张表<code>t1_exact_extracted</code>和<code>t2_exact_extracted</code>。他们两个表示相同的含义：精确地匹配而非解析包的数据。 第一个表在第一个模拟的匹配-执行阶段可以被调用，第二个表是在第二个阶段可以被调用。 在代码上的这种冗余导致只能使用配置脚本来为HyPer4生成源码。这使得HyPer4的开发变得简单，而且允许根据需求和资源进行定制。可以配置的参数包括：</p>
<ul>
<li>HyPer4必须能够模拟最大的匹配-执行阶段的最大数量</li>
<li>每个复合的动作可以执行的最大的原始操作数目</li>
<li>HyPer4可以解析的比特的默认值，最大值和步进值</li>
</ul>
<p>这些配置脚本（900行Python代码）将P4源码处理成了HyPer4可以执行的代码，它支持4个个模拟的匹配-执行pipeline的阶段而每个行为最多9个原始操作，它也支持5个P4的21个精确的原始操作。这些HyPer4的配置大约有6400行。 <a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/fd2325e07ad0c274e73520406298e0ee.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/fd2325e07ad0c274e73520406298e0ee.png" alt=""></a> 上图表示P4代码量是如何随着被模拟的匹配-执行阶段和每个阶段允许的最大原始操作数目的增长而线性增长的。其中图（a）表示整个代码量的增长，（b）关注了需要drop原始操作的代码量，而（c）是有关于<code>modify_field</code>操作的代码量。 HyPer4目前支持的五个原始操作平均的代码长度从128行（一个阶段和一个原始操作）到539行（五个阶段和九个原始操作）。外拓到16个附加原始操作（在P4中有21个），这个版本的HyPer4支持每个原始操作，除了在上图中的数字外，有超过了2000行（一个阶段和一个原始操作）到8600行（五个阶段和9个原始操作）的代码量。</p>
<h2 id="编译"><a href="#编译" class="headerlink" title="编译"></a>编译</h2><p>HyPer4编译器的开发还在进行中（很可能已经挂了或者闭源？）。 命令文件包含了所有的bmv2需要的命令，在产生这个文件之前 ，它首先会产生一个人可以阅读的中间文件。在装载后，中间命令文件将会被转化为HyPer4的命令。</p>
<h1 id="限制"><a href="#限制" class="headerlink" title="限制"></a>限制</h1><p>有一些P4的功能还没有被转化到HyPer4中。比如：</p>
<ul>
<li>有状态的内存（registers，counters，meters）</li>
<li>匹配类型：最大长度匹配，根据范围匹配</li>
<li>任意的校验和</li>
<li>字段列表</li>
<li>Expression和action profile将不会被转化为HyPer4</li>
</ul>
<h1 id="评价和分析"><a href="#评价和分析" class="headerlink" title="评价和分析"></a>评价和分析</h1><p>这里将所选的原生P4程序和被HyPer4模拟的这些P4程序进行比较。主要比较在执行的阶段匹配-执行表的阶段数目（影响时延），表、数据和动作的空间占用（影响内存）和三元组匹配的宽和频率（影响TCAM和能耗）。</p>
<h2 id="匹配-执行阶段"><a href="#匹配-执行阶段" class="headerlink" title="匹配-执行阶段"></a>匹配-执行阶段</h2><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/d817a91202dc6cd3838831c200b3ac0b.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/d817a91202dc6cd3838831c200b3ac0b.png" alt=""></a> 上表显示了HyPer4在匹配-执行阶段数目方面和P4原生代码的比较。 一般HyPer4需要大约6到7倍的匹配-执行阶段数，而arp代理则需要12倍之多。这是因为arp代理为了创建一个arp回复，这需要9个原始操作，而且这12倍的代价只发生在了收到了arp请求的时候。</p>
<h2 id="空间"><a href="#空间" class="headerlink" title="空间"></a>空间</h2><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/177316123293c19c5b1a01205e3649a1.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/177316123293c19c5b1a01205e3649a1.png" alt=""></a> 上图表明了HyPer4在不同的匹配-执行阶段和每一个阶段允许的原始操作数目一定的情况下定义的表的数目。 这里多数的表没有表项，只是为了达到模拟任意程序的需求而存在。但这些空的表也需要空间开销。 多数情况下，每一个HyPer4的表之和一个动作相关，但是一些情况下（比如执行<code>modify_field</code>原始操作的表）将达到14个操作。 以下的实验是在允许HyPer4有4个匹配-执行阶段，每个阶段有9个原始操作并且定义了346个表的情况下完成的。 <a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/0d8d2105cd2d644c269cf387cfc389bf.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/0d8d2105cd2d644c269cf387cfc389bf.png" alt=""></a> 上表表示了被不同程序所共享的表的数目。在操作的过程中，如果HyPer4托管了多个程序，那么其中许多表都被共享了。上表对角线上的元素表示每个程序自己拥有的表，因为不是所有的表在给定的程序中都有相同的分支，所以这里表的数目和前面匹配-执行阶段的表格中的数据不同。 <a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/9c4332de9fd14af218d914546d97d2d2.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/9c4332de9fd14af218d914546d97d2d2.png" alt=""></a> 上表显示了没有为其他程序共享的表的数目。显然arp_proxy有最多的特定的表。这是因为事实上只有这个程序在它的一个阶段执行过九种原始操作。 在12种情况中的8种中，程序之间共享了许多表，而不是在每个程序中都使用自己的表。 表项需要空间来存储，但是灵活性在HyPer4种更加重要，所以每个匹配都涉及解析包中的数据。框架不使用单一的800比特宽的字段，而是每一个匹配实体都需要至少1600比特来存储（800比特存储数据，800比特存储掩码）。类似地，涉及模拟元数据的匹配操作不是针对256位的字段进行，而是每个字段至少需要512个比特。程序的ID也为每个实体的bite开销增加了一些负担。所以一个用于匹配的表的前800比特用于存储包，而后256比特用于存储元数据。</p>
<h2 id="三元组匹配"><a href="#三元组匹配" class="headerlink" title="三元组匹配"></a>三元组匹配</h2><p>对三元组匹配的更多的依赖增加了能耗。 <a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/c179c5311c0999601d656a76fa7024ee.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/c179c5311c0999601d656a76fa7024ee.png" alt=""></a> 上表表示了对于每个程序产生最复杂的数据包处理时三元组匹配了多少位。total列包含了不必关心和通配符的比特，active列表示在匹配的过程中积极参与的比特数。最后一列种提供了导致前两列的三元组匹配的数目。</p>
<h2 id="时延和带宽开销"><a href="#时延和带宽开销" class="headerlink" title="时延和带宽开销"></a>时延和带宽开销</h2><p>所有的测试均使用了bmv2软件交换机，并且使用了iperf3和ping flood来完成。 测试使用的机器是运行了Mininet的Ubuntu14.04虚拟机，虚拟机拥有2.2GHz Intel Core i7-4770HQ的CPU和6.15GB的内存。 <a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/3784614287d07595cd3ac78617427fc8.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/3784614287d07595cd3ac78617427fc8.png" alt=""></a> 上表显示了十次测试的平均值和标准差，Hyper4模拟器增加了将近80%的带宽消耗和4倍左右的时延。</p>
<h2 id="在RMT中部署"><a href="#在RMT中部署" class="headerlink" title="在RMT中部署"></a>在RMT中部署</h2><p>决定了运行HyPer4能力的RMT部署细节包括了数据包头向量的长度（这使得每一个匹配-执行阶段可行，并且它既包含了用于元数据的所有比特，也包含了从包中提取的比特），物理匹配执行阶段的数量，以及每一个阶段能匹配的最大比特值。 RMT支持一个4096比特的包头向量，这达到了HyPer4使用3312比特（800比特的被解析的包数据，256比特的元数据和2256比特的其他开销）配置的要求。其他开销包括支持对分组数据的操纵的临时空间，这影响了关于如何利用可用的剩余分组包头任何决定，无论是从分组中提取更多的字节还是表示更多的元数据。 RMT在ingress pipeline和其他32个egress pipeline中包含了32个匹配-执行的阶段。在上面的示例中需要最多的匹配-执行阶段的是arp代理，它在ingress pipeline中使用了46个匹配-执行阶段，在egress中使用了两个。 RMT不能支持这种需求，但是更精确地说，将每个RTM匹配-执行阶段支持的比特数与HyPer4匹配-执行阶段所需要的比特数进行比较，可以了解在哪些情况下需要更多的物理阶段来支持给定的HyPer4匹配-执行阶段。 RMT阶段在SRAM中支持多达640比特的匹配，在TCAM中同样支持640比特。 在arp代理的46个输入阶段中，他们中的44个可以被转化为RMT物理阶段。其他的两个阶段涉及对应于80位宽字段的三元组表示提取的分组数据，并且每个需要1600位的TCAM存储器（800位存储值，800位存储掩码）。 因此，这两个HyPer4阶段的每一个需要三个RMT物理阶段。 最终总共有51个物理阶段，这比RMT的能力多60％。 请注意，这不仅将满足arp代理，而且会满足任意组合，包括arp代理和任何更简单的程序。 将32个egress匹配执行阶段中的19个转移到egress pipeline的RMT的变体可以满足今天的要求。</p>
<h1 id="另外的一些解决方案"><a href="#另外的一些解决方案" class="headerlink" title="另外的一些解决方案"></a>另外的一些解决方案</h1><p>考虑到HyPer4的性能开销较大，所以需要考虑一些替代的方案。</p>
<h2 id="部分虚拟化"><a href="#部分虚拟化" class="headerlink" title="部分虚拟化"></a>部分虚拟化</h2><p><a href="http://blog.zhengzi.me/wp-content/uploads/2017/04/4a34b8cff09ced221da79ac2a2d922db.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/04/4a34b8cff09ced221da79ac2a2d922db.png" alt=""></a> 在对性能需求比较高的硬件上使用HyPer4的全部功能会造成很大的性能开销，所以可以分的地部署HyPer4，使其可以在这些设备中流畅的运行。 P4编程模型提供了对数据包解析器以及匹配执行表进行编程的机制。对于这些程序元素，虚拟化和直接实现的各种组合以满足各种用例是可能的。 上图（a）描绘了“完整”虚拟化，每个列运行自己的程序。每个列可以同时处于活动状态（网络分片），并且数据包通过某些标准发送到特定列。 上图（b）说明了分开的虚拟解析器附加到相同的直接实现的匹配执行pipeline的可能性。 该pipeline将不会像完全虚拟化解决方案中的pipeline一样动态灵活。可以通过允许运行时可选标准来调用基于哪个数据包头被提取的不同直接实现的功能来提供有限的灵活性。 相反，如上图（c）所示，单个直接实现的解析器可以将流量传递到不同的虚拟匹配执pipeline。 这“修复”支持的协议头集，但允许不同的可动态修改的行为作为对这些头部的响应。 上图（d）表明匹配执行pipeline本身可以部分虚拟化。这对于我们愿意在一层协议栈（可能是L2或L3）中牺牲动态灵活性以满足性能的环境可能是有吸引力的，但在其他层仍然需要动态灵活性。</p>
<h2 id="其他方案"><a href="#其他方案" class="headerlink" title="其他方案"></a>其他方案</h2><ul>
<li>用于编写P4代码函数的编译器。该工具将产生一个从多个P4项目合并功能的功能。这种方法可提高性能，但不能提供运行时可重构性。</li>
<li>在应用层下实现虚拟化。这种方法可以提供具有高性能的运行时可重构性，但是需要每个平台特有的非便携式实现。</li>
<li>将P4程序直接嵌入网络。这种技术需要使用不同的程序加载不同的具有P4能力的交换机，另一个交换机根据将分组标记为属于一个虚拟网络或另一个虚拟网络的标准来选择适当的目标来处理流量。这种方法以额外的交换机为代价提供高性能和运行时可重构性（如果备用硬件可用）的可能性。</li>
</ul>
<h2 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h2><p>本文描述了一个名为HyPer4的P4虚拟化框架的概念、设计、实现和评价。它现在只能模拟P4程序的一小部分。为了使得数据平面虚拟化可以有一个便携式的解决方案，它在性能方面会造成80%到90%的损耗。它有助于运行并模拟网络中的网络功能的复杂组合，并且是一个可以为监视和程序验证功能添加有用的模块的平台。</p>
<h1 id="参考论文"><a href="#参考论文" class="headerlink" title="参考论文"></a>参考论文</h1><p>David Hancock,Jacobus van der Merwe. HyPer4: Using P4 to Virtualize the Programmable Data Plane. CoNEXT, ACM, 35-19, 2016.</p>
<blockquote>
<p><a href="http://dl.acm.org/citation.cfm?id=2999607" target="_blank" rel="noopener">HyPer4: Using P4 to Virtualize the Programmable Data Plane</a></p>
</blockquote>
<p>  本文链接<strong>：</strong><a href="http://www.sdnlab.com/18939.html" target="_blank" rel="noopener">http://www.sdnlab.com/18939.html</a></p>

          
        
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://blog.zhengzi.me/2017/03/19/e4-bd-bf-e7-94-a8bcc-e6-8f-90-e4-be-9b-e7-9a-84-e8-bd-ac-e6-8d-a2-e5-99-a8-e5-b0-86p4-e8-bd-ac-e6-8d-a2-e4-b8-baebpf-e6-b5-81-e7-a8-8b-e5-88-86-e6-9e-90/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Jason Bian">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="政子的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/03/19/e4-bd-bf-e7-94-a8bcc-e6-8f-90-e4-be-9b-e7-9a-84-e8-bd-ac-e6-8d-a2-e5-99-a8-e5-b0-86p4-e8-bd-ac-e6-8d-a2-e4-b8-baebpf-e6-b5-81-e7-a8-8b-e5-88-86-e6-9e-90/" itemprop="url">
                  使用BCC提供的转换器将P4转换为eBPF的流程分析
                </a>
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              

              
                
              

              <time title="Created: 2017-03-19 00:01:44" itemprop="dateCreated datePublished" datetime="2017-03-19T00:01:44+08:00">2017-03-19</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Modified: 2018-08-21 17:49:42" itemprop="dateModified" datetime="2018-08-21T17:49:42+08:00">2018-08-21</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/P4/" itemprop="url" rel="index"><span itemprop="name">P4</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="BPF、eBPF和IO-Visor"><a href="#BPF、eBPF和IO-Visor" class="headerlink" title="BPF、eBPF和IO Visor"></a>BPF、eBPF和IO Visor</h2><p>BPF(BerkeleyPacketFilter，伯克利数据包过滤器）允许在内核态下丢弃那些不需要的数据包，从而避免所有包都从内核态拷贝到用户态的网络监控工具而提升性能(也可采用LIBPCAP函数库实现过滤与捕捉）。 Linux 3.15 开始引入 eBPF。其扩充了 BPF 的功能，丰富了指令集。到了 eBPF 后，虚拟机的功能并都更加强大，使得我们对数据包的操作都可以在内核灵活地实现，完全不需要加载重新编译，而且可以在线替换等，灵活性大大增加。数据平面也就变得更加灵活（可以随时改变对每个数据包的处理行为）。且在内核中完成该功能使得性能大大提高（避免从内核到用户态的拷贝）。 IO Visor的基本思路是使用一种灵活的方式在内核实现对网络数据包的处理，而不需要像传统的方法那样通过加载内核模块的方式来实现、或者通过繁重的系统调用在用户态计算。从而实现一个灵活的数据平面，加速NFV。 具体说明可以参考：</p>
<ul>
<li>IO Visor仓库对于eBpf的介绍：<a href="https://github.com/iovisor/bpf-docs/blob/master/eBPF.md" target="_blank" rel="noopener">https://github.com/iovisor/bpf-docs/blob/master/eBPF.md</a></li>
<li>IO Visor官方网站：<a href="https://www.iovisor.org/technology/ebpf" target="_blank" rel="noopener">https://www.iovisor.org/technology/ebpf</a></li>
<li>Linux Kernel说明文档：<a href="https://www.kernel.org/doc/Documentation/networking/filter.txt" target="_blank" rel="noopener">https://www.kernel.org/doc/Documentation/networking/filter.txt</a></li>
</ul>
<p>所以，如果可以将P4代码转为eBPF的代码，那么它将可以直接在Linux中以原生的方式运行。可以认为eBPF能够作为类似Behavior Model的P4后端。</p>
<h2 id="P4转eBPF编译器"><a href="#P4转eBPF编译器" class="headerlink" title="P4转eBPF编译器"></a>P4转eBPF编译器</h2><h3 id="转换器"><a href="#转换器" class="headerlink" title="转换器"></a>转换器</h3><p>仓库地址：<a href="https://github.com/iovisor/bcc/tree/master/src/cc/frontends/p4" target="_blank" rel="noopener">https://github.com/iovisor/bcc/tree/master/src/cc/frontends/p4</a> 它的目的是将P4转换为C语言描述的eBPF代码片段，然后使用BCC工具来将C语言代码转换为eBPF代码，然后在Kernel中运行。</p>
<h3 id="依赖——P4-hlir"><a href="#依赖——P4-hlir" class="headerlink" title="依赖——P4-hlir"></a>依赖——P4-hlir</h3><p>仓库地址：<a href="https://github.com/p4lang/p4-hlir" target="_blank" rel="noopener">https://github.com/p4lang/p4-hlir</a> HLIR：high­level intermediate representation 它可以讲P4语言编译为P4的前端中间语言，转换器需要依赖此中间语言。</p>
<h3 id="运行环境——BCC"><a href="#运行环境——BCC" class="headerlink" title="运行环境——BCC"></a>运行环境——BCC</h3><p>仓库地址：<a href="https://github.com/iovisor/bcc" target="_blank" rel="noopener">https://github.com/iovisor/bcc</a> 使用BCC的库可以直接载入转换器转换后的C语言，并切转换为eBPF并运行。</p>
<h2 id="编译器代码分析"><a href="#编译器代码分析" class="headerlink" title="编译器代码分析"></a>编译器代码分析</h2><h3 id="文件结构（大致说明）"><a href="#文件结构（大致说明）" class="headerlink" title="文件结构（大致说明）"></a>文件结构（大致说明）</h3><p>Name</p>
<p>作用</p>
<p>compilationException.py</p>
<p>异常处理</p>
<p>ebpfAction.py</p>
<p>action相关</p>
<p>ebpfConditional.py</p>
<p>状态和跳转（if）相关</p>
<p>ebpfCounter.py</p>
<p>计数器相关</p>
<p>ebpfDeparser.py</p>
<p>Deparser相关</p>
<p>ebpfInstance.py</p>
<p>对Header、Metadata和HeaderStack的声明</p>
<p>ebpfParser.py</p>
<p>和Parser相关</p>
<p>ebpfProgram.py</p>
<p>关键控制代码，从经过hlir parser以后的中取出相关元素，生成对应的类，并且还可控制代码的翻译过程</p>
<p>ebpfScalarType.py</p>
<p>将P4的字段长度映射到C</p>
<p>ebpfStructType.py</p>
<p>和Header类型和Struct类型相关</p>
<p>ebpfTable.py</p>
<p>和match_field流表相关</p>
<p>ebpfType.py</p>
<p>转换成C语言类型的基类</p>
<p>p4toEbpf.py</p>
<p>命令行输入/调用HLIR和ebpfProgram解析P4代码，并生成C语言结构，最后输出</p>
<p>programSerializer.py</p>
<p>生成C语言代码的序列化工具</p>
<p>README.txt</p>
<p>介绍而已</p>
<p>target.py</p>
<p>配置和头文件相关</p>
<p>topoSorting.py</p>
<p>拓扑排序（这里不太明白）</p>
<p>typeFactory.py</p>
<p>header类型表</p>
<h3 id="处理流程"><a href="#处理流程" class="headerlink" title="处理流程"></a>处理流程</h3><p>总流程 <a href="http://blog.zhengzi.me/wp-content/uploads/2017/03/p42cWorkFlow.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/03/p42cWorkFlow.png" alt=""></a>构建eBPF实例的准备流程 <a href="http://blog.zhengzi.me/wp-content/uploads/2017/03/p4toEbpfWorkFlow2.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/03/p4toEbpfWorkFlow2.png" alt=""></a>转换为C语言序列化的流程</p>
<h3 id="测试用例运行流程"><a href="#测试用例运行流程" class="headerlink" title="测试用例运行流程"></a><a href="http://blog.zhengzi.me/wp-content/uploads/2017/03/p4toEbpfWorkFlow3.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/03/p4toEbpfWorkFlow3.png" alt=""></a>测试用例运行流程</h3><p>可以使用转换器目录下的test/endToEndTest.py来测试示例代码</p>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a><a href="http://blog.zhengzi.me/wp-content/uploads/2017/03/ebpfC-TEST.png"><img src="http://blog.zhengzi.me/wp-content/uploads/2017/03/ebpfC-TEST.png" alt=""></a>参考资料</h2><p>了解IO Visor的技术基石BPF与eBPF：<a href="http://blog.csdn.net/quqi99/article/details/49820419" target="_blank" rel="noopener">http://blog.csdn.net/quqi99/article/details/49820419</a></p>

          
        
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://blog.zhengzi.me/2017/03/17/e5-85-b3-e4-ba-8e-e8-b7-a8-e5-9f-9f-e9-97-ae-e9-a2-98-e7-9a-84-e4-b8-80-e4-b8-aa-e8-a7-a3-e5-86-b3-e6-96-b9-e6-b3-95/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Jason Bian">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="政子的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/03/17/e5-85-b3-e4-ba-8e-e8-b7-a8-e5-9f-9f-e9-97-ae-e9-a2-98-e7-9a-84-e4-b8-80-e4-b8-aa-e8-a7-a3-e5-86-b3-e6-96-b9-e6-b3-95/" itemprop="url">
                  关于跨域问题的一个解决方法
                </a>
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              

              
                
              

              <time title="Created: 2017-03-17 12:00:49" itemprop="dateCreated datePublished" datetime="2017-03-17T12:00:49+08:00">2017-03-17</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Modified: 2018-08-21 17:49:42" itemprop="dateModified" datetime="2018-08-21T17:49:42+08:00">2018-08-21</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/JavaScript/" itemprop="url" rel="index"><span itemprop="name">JavaScript</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="为什么要跨越"><a href="#为什么要跨越" class="headerlink" title="为什么要跨越"></a>为什么要跨越</h2><p>当需要允许其他人使用自己网站的一些API时，跨域就是一个必须要解决的问题了。</p>
<h2 id="跨域解决方案"><a href="#跨域解决方案" class="headerlink" title="跨域解决方案"></a>跨域解决方案</h2><h3 id="JsonP"><a href="#JsonP" class="headerlink" title="JsonP"></a>JsonP</h3><p>因为HTML中的标签的Src属性可以跨域，所以该方案通过动态引入<script>标签并添加Src属性完成跨域请求 但是在这种情况下，服务器不能仅仅返回一段JSON，而是要返回一段完整的JavaScript代码（比如一个函数），这样调用它的代码才能成功调用到返回的数据。并且这种情况下因为是插入了一个标签，所以在调用API的时候只能以GET方式调用（这是我的理解，或许还有其他方法可以调用POST？）。</p>
<h3 id="Ajax"><a href="#Ajax" class="headerlink" title="Ajax"></a>Ajax</h3><p>通过设置HTTP头</p>
<p>Access-Control-Allow-Origin: *</p>
<p>使得任意网站都可以直接使用Ajax像调用源站API一样来跨域访问其他站点的API 但是这种方案也有一定的限制，它只允许三种操作：GET、HEAD、POST 并且允许的Content-Type只有三种：</p>
<ul>
<li><code>application/x-www-form-urlencoded</code></li>
<li><code>multipart/form-data</code></li>
<li><code>text/plain</code></li>
</ul>
<p>注意这里并没有熟悉的application/json，所以这也给使用造成了一些困难。 这里可以参考FireFox关于跨域的开发者文档：<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS">https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS</a></p>
<h2 id="使用Ajax解决跨域的一个例子"><a href="#使用Ajax解决跨域的一个例子" class="headerlink" title="使用Ajax解决跨域的一个例子"></a>使用Ajax解决跨域的一个例子</h2><p>这里为了方便，以Angular和Node为例： 前端：</p>
<p>let url=’xxx.xxx/api/xxx’;<br>let para=’a=4’;<br>$http.post(url, para, {<br>    headers: { ‘Content-Type’: ‘application/x-www-form-urlencoded’ }<br>}).then(function (response) {<br>    console.log(response);<br>    if (response.data.success) {<br>        $scope.videoSrc = response.data.videoLink;<br>        $scope.frameVideoSrc = $sce.trustAsResourceUrl($scope.videoSrc);<br>    } else {<br>        $scope.videoSrc = response.data.errInfo;<br>    }<br>});</p>
<p>需要注意para的格式（这里是Form的上传格式）和post时候的Headers设置 后台：</p>
<p>router.post(‘/searchvideo/:vendorName?/:productId?’, function (req, res, next) {<br>    res.setHeader(“Access-Control-Allow-Origin”, “*”);<br>    console.log(req);<br>}</p>
<p>服务器这边只需要在Header里声明可以跨域就可以了</p>
<h2 id="还要完善"><a href="#还要完善" class="headerlink" title="还要完善"></a>还要完善</h2><p>在跨域的时候还遇到了Client先给Server发送Option，Server同意以后才发起跨域请求的机制，这里需要再去看一些资料，并且也还需要尝试实现以下JSONP</p>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><p>Using CORS：<a href="https://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server">https://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server</a></p>
</script></p>
          
        
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://blog.zhengzi.me/2017/03/10/e4-ba-ba-e7-b1-bb-e7-ae-80-e5-8f-b2-e6-88-91-e4-bb-ac-e5-8f-aa-e4-b8-8d-e8-bf-87-e6-98-af-e6-b2-a7-e6-b5-b7-e4-b8-80-e7-b2-9f/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Jason Bian">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="政子的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/03/10/e4-ba-ba-e7-b1-bb-e7-ae-80-e5-8f-b2-e6-88-91-e4-bb-ac-e5-8f-aa-e4-b8-8d-e8-bf-87-e6-98-af-e6-b2-a7-e6-b5-b7-e4-b8-80-e7-b2-9f/" itemprop="url">
                  人类简史——我们只不过是沧海一粟
                </a>
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              

              
                
              

              <time title="Created: 2017-03-10 09:37:52" itemprop="dateCreated datePublished" datetime="2017-03-10T09:37:52+08:00">2017-03-10</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Edited on</span>
                
                <time title="Modified: 2018-08-21 17:49:42" itemprop="dateModified" datetime="2018-08-21T17:49:42+08:00">2018-08-21</time>
              
            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/读书笔记/" itemprop="url" rel="index"><span itemprop="name">读书笔记</span></a></span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="相遇"><a href="#相遇" class="headerlink" title="相遇"></a>相遇</h2><p>最近被安利了多次“简史”类的书。很可能是因为厚本的史书已经成为了人文学院们书架上的“过时货”，而简史正成为一种更好的“快速消费”。毕竟入乡就需要随俗，那最近索性就来读一读简史类的书籍。而所读的第一本简史（如果不算《时间简史》的话）就选最近被盛誉无数的《人类简史》吧。</p>
<h2 id="诶，我们是不是在哪见过"><a href="#诶，我们是不是在哪见过" class="headerlink" title="诶，我们是不是在哪见过"></a>诶，我们是不是在哪见过</h2><p>开始概览的时候，书中的观点并没有给我带来多少惊喜或者让我难以接受的地方，多数观点我都曾见识过。 比如——被进化论支配的人类其实就是一个和猩猩差不多的物种，甚至和我们最恨的老鼠都有八成相似，而且我们在进化的齿轮中也似乎只有因果而没有目的！这些观点在学习中学生物和初读《自私的基因》的时候大都已经遇见，由此我也相信作者本人是一个博览群书并博得众长的意见传播者。又如，文化寄生的说法，我也在之前的《失控》中有遇见过。而之前在哲学通识课中，了解到了语言之于社会的重要性，而“人们所谓的意义都只是存在于自己的故事中”可能是抄写某个名人名言的时候遇到的“意义之网”之类的只言片语。对于150人理论呢，貌似是复杂网络的一些书里有提到过。 不过作者自有厉害之处，他居然可以把如此多的观点都融合进入他自己的这一套理论中。这也印证了社会物理学的一个观点：最厉害最有价值的可能不是观点的产生节点，而是将观点传播出去的节点。</p>
<h2 id="全书脉络"><a href="#全书脉络" class="headerlink" title="全书脉络"></a>全书脉络</h2><p>全书的脉络很清晰，从远古人类，到认知革命，再到农业革命，接着是全球化，进而是科学革命，最后是未来。 大概全书是从“人类很普通”开始讲起。在DNA上我们并没有太多优势，在当年许多的不同的人种里，我们的优势也就只剩下比较爱YY爱八卦。就是因为这点微小的差别，让我们和其他生物区别开来，甚至构建起了所有人类共同想象的一个大社会，成了地球上的霸主（确定霸主不是我们自己想象出来的？） 随着会使用火，又学会了种植，我们逐渐的开始定居，产生了农业革命。又因为我们的好奇心，让整个地球的人类开始走上了互坑的道路，直到近代，虽然我们遗传上来说并没有太多不同，但是依旧有一条很成体系的鄙视链。当然，这个鄙视链把我们带向了全球化。这时候，我们人类的自然认知协作能力已经到了极限，所以必须要有一种被大家共同相信的东西来让整个世界里的人类协作起来，于是有了金钱，之后因为科学主义的诞生，让我们相信未来的世界会变得更好，所以由此诞生了资本主义。最后文章讨论了一下未来（开始想象人工智能）和幸福（倒不如写一些积极心理学），不过并没有太出彩的地方。</p>
<h2 id="有意思的片段"><a href="#有意思的片段" class="headerlink" title="有意思的片段"></a>有意思的片段</h2><p>作者用了许多示例来阐释人类讲故事和编写故事的能力。 从远古图腾到近代的宗教，都是由于人们共同相信某种超自然的存在而让不熟悉的人们团结在一起。特别是作者介绍宗教脉络的章节很符合我的胃口，从泛神论到多神论再到一神论，以至于最后的二元论和非神论都有涉及，并且很清晰地整理出了其中的脉络。 不仅仅如此，我们的帝国和法律，甚至连货币也都是共同想象的产物，因为我们相信，所以才会存在。虽然是超越的存在，但在我们的大脑里，却是如此的真实。而我们现在也正要把这种超越的存在（不知是不是可以用层层隐喻来解释这个体系），变成像我们这样的现实存在。 我们的资本主义/人本主义/人文主义/社会主义，不也是如此？正因为我们都相信，所以才会存在。我们现在所享有的这一切，并不是应该有的，而是在无数先烈英杰们的伟大思想和流血牺牲中才逐渐让大家都相信和接受的。虽然这些都是超越而抽象的存在，但对于我们人类是多么的重要，这一切是多么的真实。 另一个有意思的地方是作者关于历史的论述。 历史上的每一个时间点，都像是一个十字路口。虽然从过去到现在已经只剩单行道，但到未来却有无数岔路可走。其中某些路比较宽、比较平坦，路标比较明确，所以也是比较可能的选择。然而，历史有时候就是选了一些完全出人意表的道路。 乔布斯也说过类似的话，他说之前学过的看似无用的课程（譬如他学习关于字体的课程）就像一颗颗散落的珍珠一样，到了后来，才会逐渐发现原来有一条线，可以将他们一一串起，变成一整条珍珠项链。这句话我也经常转述给他人。</p>
<h2 id="提问时间"><a href="#提问时间" class="headerlink" title="提问时间"></a>提问时间</h2><p>作者的理论对于艺术没有一个很好的解释，为何人们对于艺术作品（多数也是超越之物）可以产生愉悦感，而这和历史有什么关系？莫非艺术也源于人们的共同向想，但是我们并不是相信或者喜欢艺术作品里的某个故事，只是有一种说不出的赏心悦目呀？ 另外一个问题就是关于自由和平等互斥的论述，我觉得不能接受。我认为的自由指的是社会意义上自由，如孟子所言“随心所欲而不逾矩”，而平等在我眼里也并不等于平均。虽说这两者很难同时得兼，但也并不存在可以拿得出说的矛盾之处。所以矛盾之处到底在哪里呢？ 最后一个疑问是这本书作为一个商业读物，是不是并不会非常客观地描述所有观点，而有所取舍地使用一些观点来提升销量？对于同样的事实，解释的理论不同，得到的结论可能会大相径庭，作者会不会隐藏掉了许多更加合理解释？在全文，没有见到作者对人类（哪怕是自己）先天观点的分析。在最后作者关于幸福心理的论述中更给我一种他希望紧扣时代心理成为畅销书而强行加入内容的感觉。所以，到底有多少观点和他的观点是相对或者相反？这需要做更大量的类比阅读，才会有答案。</p>
<h2 id="向混沌致敬"><a href="#向混沌致敬" class="headerlink" title="向混沌致敬"></a>向混沌致敬</h2><p>我们从哪来，到哪去？为何而来，为何而去？虽然我们使用人类特有的想象赋予我们的世界以意义，但是这些关于意义最根本的问题我们可能眼前只有一片混沌，永远也无法回答。可能是因为我们本身的局限（我虽然很小心，但还在这里用了“因为”二字，然而我们这个世界真的是具有因果关系的么？这无法确实——休谟问题一），就比如刚刚因为“因为”二字所起的疑惑。大概是我们大脑的先天因素造成的整个局限，我们并不能用我们的知识体系解决一切问题。所以，现代的科学主义所认为的进步真的会是无穷的么？而进步的具体定义又是什么？就算有人给出了定义，那我们把它们放在范畴中讨论就真的合适么？ 这一系列的问题，答案可能都是混沌。 所以，为何要被这么多的意义捆绑？为什么事事都要争先恐后？ 不如骑一辆小黄车，去奥森公园呼吸一下春天的空气，然后再饱餐一顿？ @在没有微软的纯洁世界里 的全体成员，走起！ <a href="http://music.163.com/#/song?id=418602453" target="_blank" rel="noopener">http://music.163.com/#/song?id=418602453</a></p>

          
        
      
    </div>

    

    
    
    

    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
  </section>

  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/"><i class="fa fa-angle-left" aria-label="Previous page"></i></a><a class="page-number" href="/">1</a><span class="page-number current">2</span><a class="page-number" href="/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/page/9/">9</a><a class="extend next" rel="next" href="/page/3/"><i class="fa fa-angle-right" aria-label="Next page"></i></a>
  </nav>



          </div>
          

        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      

      <section class="site-overview-wrap sidebar-panel sidebar-panel-active">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image"
                src="/images/avatar.jpg"
                alt="Jason Bian" />
            
              <p class="site-author-name" itemprop="name">Jason Bian</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          
            <nav class="site-state motion-element">
              
                <div class="site-state-item site-state-posts">
                
                  <a href="/archives/">
                
                    <span class="site-state-item-count">86</span>
                    <span class="site-state-item-name">posts</span>
                  </a>
                </div>
              

              
                
                
                <div class="site-state-item site-state-categories">
                  
                    
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                    <span class="site-state-item-count">41</span>
                    <span class="site-state-item-name">categories</span>
                  
                </div>
              

              
                
                
                <div class="site-state-item site-state-tags">
                  
                    
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                    <span class="site-state-item-count">109</span>
                    <span class="site-state-item-name">tags</span>
                  
                </div>
              
            </nav>
          

          

          

          
          

          
          

          
            
          
          

        </div>
      </section>

      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2018</span>
  <span class="with-love" id="animate">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Jason Bian</span>

  

  
</div>




  <div class="powered-by">Powered by <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a></div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">Theme – <a class="theme-link" target="_blank" href="https://theme-next.org">NexT.Gemini</a></div>




        








        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    
	
    

    
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>


























  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=6.4.0"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=6.4.0"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=6.4.0"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=6.4.0"></script>



  

  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=6.4.0"></script>



  



  










  





  

  

  

  

  
  

  

  

  

  

  

</body>
</html>
